home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_dos.lha / dos / sphsrc.v08 / sph_view.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-26  |  13.2 KB  |  504 lines

  1. #include "HEADERS.h"
  2. #include "sphigslocal.h"
  3. #include <stdio.h>
  4.  
  5. #define THE_VIEW    SPH_viewTable[viewIndex]
  6.  
  7. #define FEPS         (1e-12)
  8. #define FZERO(N)      ((N) < FEPS && (N) > -FEPS)
  9. #define FEQUAL(A,B)      (((A) - (B)) < FEPS && ((A) - (B)) > -FEPS)
  10.  
  11. #define PI            3.1415926535
  12.  
  13.  
  14.  
  15. /*!*/
  16. void 
  17. SPH_evaluateViewOrientationMatrix 
  18.    (point view_ref_point,
  19.     vector view_plane_normal, vector view_up_vector,
  20.     matrix vo_matrix /*varparm*/ )
  21. {
  22.    vector tempvec, up_v, normal_v, proj_up_v, right_v;
  23.    matrix trans, rot;
  24.    double dot, tmp1;
  25.  
  26.  
  27.    /* FIND THE UNIT VERSION OF THE up VECTOR */
  28.    MAT3_COPY_VEC(up_v, view_up_vector);
  29.    MAT3_NORMALIZE_VEC(up_v, tmp1);
  30.    if (tmp1 == 0.0)
  31.       SPH__error (ERR_MAT3_PACKAGE, "up vector has zero length");
  32.  
  33.    /* FIND THE UNIT VERSION OF THE view plane normal VECTOR */
  34.    MAT3_COPY_VEC(normal_v, view_plane_normal);
  35.    MAT3_NORMALIZE_VEC(normal_v, tmp1);
  36.    if (tmp1 == 0.0)
  37.       SPH__error (ERR_MAT3_PACKAGE, "View plane normal has zero length");
  38.  
  39.    /* Find the projection of the up vector on the film plane */
  40.    dot = MAT3_DOT_PRODUCT(up_v, normal_v);
  41.    if (dot == 1.0 || dot == -1.0)
  42.       SPH__error (ERR_MAT3_PACKAGE, "Up vector and view plane normal are the same");
  43.  
  44.    MAT3_LINEAR_COMB(proj_up_v, 1.0, up_v, -dot, normal_v);
  45.    MAT3_NORMALIZE_VEC(proj_up_v, tmp1);
  46.  
  47.    /* Find the vector that goes to the right on the film plane */
  48.    MAT3cross_product(right_v,    normal_v, proj_up_v);
  49.  
  50.  
  51. /*!*/
  52.    /********* STEP 1 OF FOLEY CHAPTER VIEW.5.2 */
  53.    /* Translate view reference point to origin */
  54.    MAT3_SCALE_VEC(tempvec, view_ref_point, -1);
  55.    MAT3translate(trans, tempvec);
  56.  
  57.  
  58.    /********* STEP 2 OF FOLEY CHAPTER VIEW.5.2 */
  59.    /* Rotate so normal lies on z-axis and proj_up is on y-axis */
  60.    /* Remember: right-hand rule is in effect. */
  61.    MAT3identity(rot);
  62.    rot[0][2] = normal_v[X];
  63.    rot[1][2] = normal_v[Y];
  64.    rot[2][2] = normal_v[Z];
  65.  
  66.    rot[0][0] = -right_v[X];
  67.    rot[1][0] = -right_v[Y];
  68.    rot[2][0] = -right_v[Z];
  69.  
  70.    rot[0][1] = proj_up_v[X];
  71.    rot[1][1] = proj_up_v[Y];
  72.    rot[2][1] = proj_up_v[Z];
  73.  
  74.  
  75.    /*************** PRODUCE THE FINAL PRODUCT: TRANS x ROT */
  76.    MAT3mult(vo_matrix,   trans, rot);
  77. }
  78.  
  79.  
  80.  
  81.  
  82. /*!*/
  83.  
  84.  
  85. static double most_recent_F, most_recent_B;
  86.  
  87.  
  88.  
  89. void
  90. SPH_evaluateViewMappingMatrix
  91.    (double umin, double umax, double vmin, double vmax,
  92.     int proj_type,  /* ORTHOGRAPHIC or PERSPECTIVE */
  93.     point proj_ref_point,
  94.     double front_plane_dist, double back_plane_dist,
  95.     double viewport_minx, 
  96.     double viewport_maxx, 
  97.     double viewport_miny, 
  98.     double viewport_maxy,
  99.     double viewport_minz, 
  100.     double viewport_maxz,
  101.     matrix vm_matrix /*varparm*/ )
  102. {
  103.    matrix step3_matrix, step4_matrix, step3and4_matrix, step5_matrix,
  104.           step6_matrix, sklar_matrix;
  105.    MAT3hvec vrp;
  106.  
  107.    MAT3_SET_HVEC (vrp, 0.0, 0.0, 0.0, 1.0);
  108.  
  109. /*!*/
  110.  
  111.    /**** First, we test for "garbage in" ****/
  112.    if (proj_ref_point[Z] <= 0.0)
  113.       SPH__error (ERR_BAD_VIEWING_PARAMETER, 
  114.           "proj_ref_point[Z] is zero or negative\n");
  115.    if (front_plane_dist >= proj_ref_point[Z])
  116.       SPH__error (ERR_BAD_VIEWING_PARAMETER, 
  117.          "front clip plane lies behind or on the PRP\n");
  118.    if (back_plane_dist >= front_plane_dist)
  119.       SPH__error (ERR_BAD_VIEWING_PARAMETER, 
  120.          "back clip plane is closer to PRP than the front clip plane");
  121.  
  122.  
  123.    /**** Save the F and B because currently there's a bug in ORTHO mode;
  124.          we can't backcalc the F and B from the vm matrix in ORTH mode! ***/
  125.    if (proj_type == ORTHOGRAPHIC) {
  126.       most_recent_F = front_plane_dist;
  127.       most_recent_B = back_plane_dist;
  128.    }
  129.  
  130.    /********* STEP 3 OF FOLEY CHAPTER VIEW.5.2 */
  131.    /* Only to be done for PERSPECTIVE. */
  132.    /* Translate so the PRP (center of projection) is at the origin. */
  133.    if (proj_type == PERSPECTIVE) {
  134.       vector tempvec;
  135.  
  136.       MAT3_SCALE_VEC(tempvec, proj_ref_point, -1);
  137.       MAT3translate(step3_matrix, tempvec);
  138. #ifdef DEBUG
  139.       MAT3print_formatted
  140.      (step3_matrix, stdout, 0, "Foley step 3  ", 0, 0); 
  141. #endif
  142.       
  143.       /* update vrp */
  144.       MAT3_ADD_VEC(vrp,  vrp, tempvec);
  145.    }
  146.    else
  147.       MAT3identity (step3_matrix);
  148.  
  149.  
  150.  
  151. /*!*/   
  152.    /********* STEP 4 OF FOLEY CHAPTER VIEW.5.2 */
  153.    /* Shear so that the center line of the view volume lies on z-axis */
  154.    {
  155.       vector dop_v;   /* direction of projection */
  156.  
  157.       if (proj_type == PERSPECTIVE) {
  158.      dop_v[0] = vrp[0] + (umax+umin)/2;
  159.      dop_v[1] = vrp[1] + (vmax+vmin)/2;
  160.      dop_v[2] = vrp[2];
  161.       }
  162.       else {
  163.      dop_v[0] = (umax+umin)/2 - proj_ref_point[0];
  164.      dop_v[1] = (vmax+vmin)/2 - proj_ref_point[1];
  165.      dop_v[2] = 0.0 - proj_ref_point[2];
  166.       }
  167.  
  168.       MAT3shear(step4_matrix, -dop_v[X] / dop_v[Z], -dop_v[Y] / dop_v[Z]);
  169. #ifdef DEBUG
  170.       MAT3print_formatted
  171.         (step4_matrix, stdout, 0, "Shear  ", 0, 0); 
  172. #endif
  173.    }
  174.  
  175.  
  176.  
  177.    
  178.  
  179. /*!*/   
  180.    /* LET'S COMPUTE THE INTERMEDIATE RESULT: step3 times step4 */
  181.    MAT3mult (step3and4_matrix, step3_matrix, step4_matrix);
  182. #ifdef DEBUG
  183.    MAT3print_formatted
  184.       (step3and4_matrix, stdout, 0, "Foley step 3 x step 4  ", 0, 0); 
  185. #endif
  186.  
  187.  
  188. /*!*/
  189.    /* STEPS 5 and 6 DIFFER BETWEEN THE TWO TYPES OF PROJECTIONS. */
  190.  
  191.    if (proj_type == ORTHOGRAPHIC) {
  192.       vector tempvec;
  193.       MAT3_SET_VEC (tempvec,  
  194.             (umax+umin)/(-2.0),
  195.             (vmax+vmin)/(-2.0),
  196.             0.0);            /******** F=0.0 */
  197.       MAT3translate(step5_matrix, tempvec);
  198. #ifdef DEBUG
  199.       MAT3print_formatted
  200.         (step5_matrix, stdout, 0, "ORTHO step Tpar w/ F=0  ", 0, 0); 
  201. #endif
  202.  
  203.       MAT3_SET_VEC (tempvec,  
  204.             2.0/(umax-umin),
  205.             2.0/(vmax-vmin),
  206.             1.0/2.0);            /******** B=2.0 */
  207.       MAT3scale(step6_matrix, tempvec);
  208. #ifdef DEBUG
  209.       MAT3print_formatted
  210.         (step6_matrix, stdout, 0, "ORTHO step Spar w/ B=2  ", 0, 0); 
  211. #endif
  212.    }
  213.    else {
  214. /*!*/   
  215.    /********* STEP 5 OF FOLEY CHAPTER VIEW.5.2 */
  216.    /* Get it to canonical perspective volume. */
  217.       MAT3hvec vrp_prime;
  218.       vector scale_vec;
  219.       double zmin;
  220.  
  221.       /* FIRST, find VRP' (VRP after steps 3 and 4) */
  222.       MAT3mult_hvec (vrp_prime, vrp, step4_matrix, FALSE);
  223. #ifdef DEBUG
  224.       printf ("vrp_prime is found to be: (%f %f %f %f)\n",
  225.           vrp_prime[0], vrp_prime[1], vrp_prime[2], vrp_prime[3]);
  226. #endif
  227.  
  228.       /* Compute a scale matrix ala Foley */
  229. #     define F front_plane_dist
  230. #     define B back_plane_dist
  231.       MAT3_SET_VEC(scale_vec,
  232.            (2.0)*vrp_prime[Z]/((umax-umin)*(vrp_prime[Z]+B)),
  233.            (2.0)*vrp_prime[Z]/((vmax-vmin)*(vrp_prime[Z]+B)),
  234.            1.0/(vrp_prime[Z]+B));
  235.  
  236.       MAT3scale(step5_matrix, scale_vec);
  237. #ifdef DEBUG
  238.       MAT3print_formatted
  239.         (step5_matrix, stdout, 0, "Foley step 5 w/ B=2  ", 0, 0); 
  240. #endif
  241.  
  242. /*!*/
  243.    /************ STEP 6 OF FOLEY */
  244.    /* Get it to canonical parallel volume. */
  245.    
  246.    
  247.       zmin = (vrp_prime[Z]+F)/(vrp_prime[Z]+B);
  248. #ifdef DEBUG
  249.       fprintf (stderr, "VIEW MAPPING MATRIX CALC'D FOR    F=%f  B=%f\n", F,B);
  250.       fprintf (stderr, "zmin is calculated as %f\n", zmin);
  251. #endif
  252.       MAT3zero (step6_matrix);
  253.       step6_matrix[0][0] = 1.0;
  254.       step6_matrix[1][1] = 1.0;
  255.       step6_matrix[2][2] = 1.0 / (1.0 - zmin);
  256.       step6_matrix[3][2] = (0.0 - zmin) / (1.0 - zmin);
  257.       step6_matrix[2][3] = 1.0;
  258. #ifdef DEBUG
  259.       MAT3print_formatted
  260.         (step6_matrix, stdout, 0, "Foley step 6 w/ F=0  ", 0, 0); 
  261. #endif
  262.    }
  263.  
  264.   
  265. /*!*/   
  266.    /******** DO SOME MERGING */
  267.    MAT3mult(vm_matrix,   step3and4_matrix, step5_matrix);
  268.    MAT3mult(vm_matrix,   vm_matrix, step6_matrix);
  269. #ifdef DEBUG
  270.    MAT3print_formatted
  271.          (vm_matrix, stdout, 0, "All of Foley's steps  ", 0, 0); 
  272. #endif
  273.  
  274.  
  275. /*!*/
  276.    /********* SKLAR'S STEP */
  277.    /* To bring the canonical (-1 to +1) to the NPC viewport.
  278.     * This transformation will produce NDC coordinates (if you ignore z).
  279.     */
  280.    {
  281.       matrix scalemat, transmat;
  282.       vector scale_vec, trans_vec;
  283.  
  284.       MAT3_SET_VEC(scale_vec,
  285.            (viewport_maxx - viewport_minx)/2,
  286.            (viewport_maxy - viewport_miny)/2,
  287.            1.0);
  288.       MAT3scale(scalemat,   scale_vec);
  289.       MAT3_SET_VEC(trans_vec,
  290.            (viewport_minx+viewport_maxx)/2,
  291.            (viewport_miny+viewport_maxy)/2,
  292.            0);
  293.       MAT3translate(transmat,   trans_vec);
  294.  
  295.       MAT3mult(sklar_matrix,   scalemat, transmat);
  296.    }
  297.  
  298.    MAT3mult(vm_matrix,   vm_matrix, sklar_matrix);
  299.    
  300. #ifdef DEBUG
  301.    MAT3print_formatted
  302.          (vm_matrix, stdout, 0, "Final matrix  ", 0, 0); 
  303. #endif
  304. }
  305.  
  306.  
  307.  
  308.  
  309.  
  310. /** SPH_translateWCtoPDC
  311. Translates a single point.
  312. **/
  313. void
  314. SPH__translateWCtoPDC (int viewIndex, MAT3hvec inpt, MAT3hvec outpt)
  315. {
  316.    MAT3mult_hvec (outpt, inpt, THE_VIEW.cammat, TRUE);
  317. }
  318.  
  319.  
  320.  
  321. /** SPH_translateMCtoPDC
  322. Translates a single point from MC to PDC by 
  323. multiplying by the TOTAL transform matrix.
  324. **/
  325. void
  326. SPH__translateMCtoPDC (matrix xformmat, MAT3hvec inpt, MAT3hvec outpt)
  327. {
  328.    MAT3mult_hvec (outpt, inpt, xformmat, TRUE);
  329. }
  330.  
  331.  
  332.  
  333.  
  334.  
  335. /** SPH_update_view_info
  336. Upon entry, the vo_matrix, vm_matrix, and viewport for the given view can
  337. be assumed correct, but the pdc-viewport and the final viewing matrix
  338. are obsolete and must be recomputed.
  339. **/
  340.  
  341. void SPH__updateViewInfo (int viewIndex)
  342. {
  343.    vector scale_vec;
  344.    matrix scale_mat;
  345.  
  346.  
  347.    THE_VIEW.pdc_viewport.bottom_left.x =
  348.        THE_VIEW.viewport.bottom_left.x * SPH_ndcSpaceSizeInPixels;
  349.    THE_VIEW.pdc_viewport.bottom_left.y =
  350.        THE_VIEW.viewport.bottom_left.y * SPH_ndcSpaceSizeInPixels;
  351.    THE_VIEW.pdc_viewport.top_right.x =
  352.       (THE_VIEW.viewport.top_right.x * SPH_ndcSpaceSizeInPixels) - 1;
  353.    THE_VIEW.pdc_viewport.top_right.y =
  354.       (THE_VIEW.viewport.top_right.y * SPH_ndcSpaceSizeInPixels) - 1;
  355.  
  356.    /* ONE FINAL STEP.  The transformation after the view-orientation
  357.       and the view-mapping produces NDC coords (NPC, to PHIGS-gurus).
  358.       We need to scale that by the pixel-size of our NDC space to
  359.       get PDCs.
  360.       The Z-coord of the PDC coord is being scaled quite substantially
  361.          so when we turn it into an integer via truncation it doesn't
  362.      lose its meaning.  It will be used for HLHSR.
  363.     */
  364.    MAT3mult (THE_VIEW.cammat, THE_VIEW.vo_matrix, THE_VIEW.vm_matrix);
  365.    MAT3_SET_VEC(scale_vec,  
  366.         SPH_ndcSpaceSizeInPixels*1.0,
  367.         SPH_ndcSpaceSizeInPixels*1.0,
  368.         1000.0);
  369.    MAT3scale (scale_mat, scale_vec);
  370.    MAT3mult (THE_VIEW.cammat,    THE_VIEW.cammat, scale_mat);
  371. }
  372.  
  373.    
  374.  
  375.  
  376. /** SPH_init_view_table
  377. **/
  378. void SPH__init_view_table (void)
  379. {
  380.    register viewIndex=0;
  381.    register view_spec *v;
  382.    point vrp, prp;
  383.    vector vpn, vupv;
  384.    matrix vo_matrix, vm_matrix;
  385.  
  386.    SPH_evaluateViewOrientationMatrix 
  387.       (SPH_defPoint(vrp,  0.0,0.0,0.0),
  388.        SPH_defPoint(vpn,  0.0,0.0,1.0),
  389.        SPH_defPoint(vupv, 0.0,1.0,0.0),
  390.        vo_matrix);
  391.  
  392.    SPH_evaluateViewMappingMatrix
  393.       (0.0,1.0,  0.0,1.0,
  394.        ORTHOGRAPHIC,
  395.        SPH_defPoint(prp,  0.5,0.5,1.0),
  396.        0.99, -50000.0,
  397.        0.0,1.0, 0.0,1.0, 0.0, 1.0,
  398.        vm_matrix);
  399.  
  400.    bzero (SPH_viewTable, sizeof(view_spec)*(MAX_VIEW_INDEX+1));
  401.  
  402. #if defined(THINK_C) || defined(__MSDOS__)
  403. #define HUGE ((double)9999999.0)
  404. #endif
  405.    v = SPH_viewTable;
  406.    for (viewIndex=0; viewIndex<=MAX_VIEW_INDEX; viewIndex++) {
  407.       SPH_setViewRepresentation
  408.      (viewIndex,
  409.       vo_matrix, vm_matrix,
  410.       0.0,1.0, 0.0,1.0, 0.0,1.0);
  411.       ClearBitstring (&v->descendent_list);
  412.       v->rendermode = WIREFRAME;
  413.       v->background_color = SRGP_WHITE;
  414.       MAT3_SET_VEC (v->uvn_point_light_source, 0.0, HUGE, HUGE);
  415.       v++;
  416.    }
  417. }
  418.  
  419.  
  420.  
  421. /** SPH_setViewBackgroundColor
  422. On a per-view basis, the background color can be set. 
  423. Warning: this does NOT cause a refresh.  The new color will only
  424.    be seen upon the next operation causing a refresh.
  425. **/
  426.  
  427. void SPH_setViewBackgroundColor (int viewIndex, int color)
  428. {
  429.    if ( ! IS_LEGAL_COLOR_INDEX(color))
  430.       color = 0;
  431.    SPH_viewTable[viewIndex].background_color = color;
  432. }
  433.    
  434.  
  435.  
  436.  
  437. /** SPH_setViewRepresentation
  438. **/
  439. void 
  440. SPH_setViewRepresentation 
  441.    (int viewIndex,
  442.     matrix vo_matrix, matrix vm_matrix,
  443.     double vp_minx, double vp_maxx, 
  444.     double vp_miny, double vp_maxy,
  445.     double vp_minz, double vp_maxz)
  446. {
  447.    srgp__rectangle oldpdcviewport;
  448.    MAT3hvec testvec = {0.0, 0.0, 0.0, 1.0}, resultvec;
  449.    matrix inverse_vm_matrix;
  450.  
  451.  
  452.    SPH_check_system_state;
  453.    SPH_check_no_open_structure;
  454.    SPH_check_view_index;
  455.  
  456.    SPH_check_rectangle (vp_minx,vp_miny,vp_maxx,vp_maxy);
  457.  
  458.    oldpdcviewport = THE_VIEW.pdc_viewport;
  459.    THE_VIEW.viewport = 
  460.       SPH_defNDCrectangle (vp_minx, vp_miny, vp_maxx, vp_maxy);
  461.               
  462.    MAT3copy (THE_VIEW.vo_matrix,   vo_matrix);
  463.    MAT3copy (THE_VIEW.vm_matrix,   vm_matrix);
  464.    
  465.    MAT3invert (inverse_vm_matrix,  vm_matrix);
  466.    
  467.    MAT3mult_hvec (resultvec, testvec, inverse_vm_matrix, TRUE);
  468.    THE_VIEW.frontPlaneDistance = resultvec[Z];
  469.   
  470. #ifdef DEBUG
  471.    fprintf (stderr, "Backcalcing the F from z=0 results in %f\n", resultvec[Z]);
  472. #endif
  473.  
  474.    testvec[Z] = 1.0;
  475.    MAT3mult_hvec (resultvec, testvec, inverse_vm_matrix, TRUE);
  476.    THE_VIEW.backPlaneDistance = resultvec[Z];
  477.    
  478. #ifdef DEBUG
  479.    fprintf (stderr, "Backcalcing the B from z=1 results in %f\n", resultvec[Z]);
  480. #endif
  481.  
  482.    if (THE_VIEW.frontPlaneDistance <= THE_VIEW.backPlaneDistance) {
  483.       /**** WHOA!  Bad news!  Can't backcalc (happens in ORTHO matrices) ***/
  484.       /* We'll have to take a not-so-wild guess. */
  485.       THE_VIEW.frontPlaneDistance = most_recent_F;
  486.       THE_VIEW.backPlaneDistance = most_recent_B;
  487.    }
  488.  
  489.    SPH__updateViewInfo (viewIndex);
  490.    SPH__refresh_viewport_change (viewIndex, oldpdcviewport);
  491.  
  492. }
  493.  
  494.  
  495.  
  496.  
  497. void
  498. SPH_setViewPointLightSource (int viewIndex, double u, double v, double n)
  499. {
  500.    MAT3_SET_VEC (THE_VIEW.uvn_point_light_source,
  501.          u,v,n);
  502.    SPH_regenerateScreen();
  503. }
  504.